﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;

namespace LiSAClient.WpfClient.Resources
{
    public class ContentDataTemplateSelector : DataTemplateSelector
    {
        private readonly Dictionary<string, Type> viewModelTypeNameViewTypeMap;

        public ContentDataTemplateSelector()
        {
            this.viewModelTypeNameViewTypeMap = new Dictionary<string, Type>();

            // register local views
            var allLocalTypes = typeof(ContentDataTemplateSelector).Assembly.GetTypes();

            // The views just have to be contained within the Views folder or any of its subfolders.
            var localViewTypes = allLocalTypes.Where(x => x.Namespace == "LiSAClient.WpfClient.View" || x.Namespace.StartsWith("LiSAClient.WpfClient.View."));

            // register contents views
            foreach (var viewType in localViewTypes)
            {
                var viewModelName = string.Format("{0}ViewModel", viewType.Name);
                this.viewModelTypeNameViewTypeMap[viewModelName] = viewType;
            }
        }

        public override DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container)
        {
            if (item == null)
            {
                return base.SelectTemplate(item, container);
            }

            var viewModelType = item.GetType();
            Type viewType = null;
            if (!this.viewModelTypeNameViewTypeMap.TryGetValue(viewModelType.Name, out viewType))
            {
                return base.SelectTemplate(item, container);
            }

            return this.CreateTemplate(viewModelType, viewType);
        }

        private DataTemplate CreateTemplate(Type viewModelType, Type viewType)
        {
            const string xamlTemplate = "<DataTemplate DataType=\"{{x:Type vm:{0}}}\"><v:{1} /></DataTemplate>";
            var xaml = String.Format(xamlTemplate, viewModelType.Name, viewType.Name);

            var context = new ParserContext();
            context.XamlTypeMapper = new XamlTypeMapper(new string[0]);
            context.XamlTypeMapper.AddMappingProcessingInstruction("vm", viewModelType.Namespace, viewModelType.Assembly.FullName);
            context.XamlTypeMapper.AddMappingProcessingInstruction("v", viewType.Namespace, viewType.Assembly.FullName);

            context.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
            context.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
            context.XmlnsDictionary.Add("vm", "vm");
            context.XmlnsDictionary.Add("v", "v");

            var template = (DataTemplate)XamlReader.Parse(xaml, context);
            return template;
        }
    }
}

